// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package admin_api_impl

import (
	"encoding/json"
	"fmt"

	"gitcode.com/openseaotter/so_proto_gen_go.git/admin_api"
	"gitcode.com/openseaotter/so_server/config"
	"gitcode.com/openseaotter/so_server/manifest_impl"
	"gitcode.com/openseaotter/so_server/storage"
)

type AdminApiImpl struct {
	admin_api.UnimplementedAdminApiServer
}

func (apiImpl *AdminApiImpl) Gc(req *admin_api.GcRequest, s admin_api.AdminApi_GcServer) error {
	cfg, err := config.ReadServerConfigFromCache()
	if err != nil {
		return err
	}

	if cfg.SuperToken == "" || req.AccessToken != cfg.SuperToken {
		s.Send(&admin_api.GcResponse{
			Code:   admin_api.GcResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		})
		return nil
	}

	refItemList, err := storage.ImageReferenceDao.ListAll(s.Context())
	if err != nil {
		return err
	}

	blobIdResult := &manifest_impl.CollectBlobIdResult{}
	for _, refItem := range refItemList {
		if refItem.ContentType == manifest_impl.DOCKER_MANIFEST_TYPE {
			obj := &manifest_impl.DockerManifest{}
			err := json.Unmarshal([]byte(refItem.Content), obj)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
			obj.CollectBlobId(blobIdResult)
		} else if refItem.ContentType == manifest_impl.OCI_MANIFEST_TYPE {
			obj := &manifest_impl.OciManifest{}
			err := json.Unmarshal([]byte(refItem.Content), obj)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
			obj.CollectBlobId(blobIdResult)
		} else if refItem.ContentType == manifest_impl.DOCKER_MANIFEST_LSIT_TYPE {
			obj := &manifest_impl.DockerManifestList{}
			err := json.Unmarshal([]byte(refItem.Content), obj)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
			err = obj.CollectBlobId(blobIdResult)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
		} else if refItem.ContentType == manifest_impl.OCI_MANIFEST_LIST_TYPE {
			obj := &manifest_impl.OciManifestList{}
			err := json.Unmarshal([]byte(refItem.Content), obj)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
			err = obj.CollectBlobId(blobIdResult)
			if err != nil {
				if req.SkipError {
					continue
				}
				return err
			}
		} else {
			return fmt.Errorf("unkwown content type %s", refItem.ContentType)
		}
	}

	blobIdMap := map[string]bool{}

	for _, blobId := range blobIdResult.BlobIdList {
		blobIdMap[blobId] = true
	}

	err = storage.BlobStore.Walk(uint(req.DayBefore), func(blobId string) {
		if !blobIdMap[blobId] {
			storage.BlobStore.Remove(blobId) // skip error check
			s.Send(&admin_api.GcResponse{
				Code:         admin_api.GcResponse_CODE_OK,
				RemoveBlobId: blobId,
			})
		}
	})

	if err != nil {
		return err
	}
	return nil
}
